home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
sr
/
info.lha
/
info-sr.1989
< prev
next >
Wrap
Text File
|
1993-07-24
|
93KB
|
3,033 lines
From wagnerj@iris.ucdavis.edu Mon Jun 26 00:18:51 1989
Received: from clover.ucdavis.edu by megaron.arizona.edu (5.59-1.7/15) via SMTP
id AA01181; Mon, 26 Jun 89 00:18:51 MST
Received: from iris.ucdavis.edu by clover.ucdavis.edu (5.59/UCD.EECS.1.10)
id AA01126; Mon, 26 Jun 89 00:18:27 PDT
Received: by iris (1.2/3.14)
id AA21073; Mon, 26 Jun 89 00:15:36 pdt
Date: Mon, 26 Jun 89 00:15:36 pdt
From: wagnerj@iris.ucdavis.edu (John Michael Wagner)
Message-Id: <8906260715.AA21073@iris>
To: info-sr@arizona.edu
I am trying to port SR to the Sun 4, working with Dr. Ron Olsson.
The SPARC architecture is new to me, as is assembly. The major
routines, possibly the only routines, I need to port are, of
course, the run-time support routines for sr_build_context,
etc. The Mips is also a RISC machine, but totally different; I
thought it might be of help, but I don't think that will be the case.
My major stumbling block is, at this time, which registers need to
be saved. Everything else is rather trivial. Perhaps there
is someone else interested in this port who knows Sun 4 assembly
and, more specifically, the C/assembly interface. Any help/
suggestions/comments would be appreciated. E-mail me at
wagnerj@iris.ucdavis.edu
Thanks in advance for any/all replies!
-John Wagner
From gmt Thu Jul 27 10:24:41 1989
Date: Thu, 27 Jul 89 10:24:41 MST
From: "Gregg Townsend" <gmt>
Message-Id: <8907271724.AA06369@megaron.arizona.edu>
Received: by megaron.arizona.edu (5.59-1.7/15)
id AA06369; Thu, 27 Jul 89 10:24:41 MST
To: info-sr
Subject: announcing SR version 1.1
A revised implementation of the SR programming language is now available from
the University of Arizona by anonymous FTP or by mail. The new version is a
little faster, a little more robust, and a lot more portable. Some minor
changes and enhancements have also been made to the language itself.
[I'll post the release notes as a separate message.]
SR (Synchronizing Resources) is designed for writing distributed programs.
The main language constructs are resources and operations. Resources
encapsulate processes and variables they share; operations provide the primary
mechanism for process interaction. SR provides a novel integration of the
mechanisms for invoking and servicing operations. Consequently, all of local
and remote procedure call, rendezvous, message passing, dynamic process
creation, multicast, and semaphores are supported. An overview of the
language and implementation appeared in the January, 1988, issue of TOPLAS
(ACM Transactions on Programming Languages and Systems 10,1, 51-86).
SR has been used at a number of universities and labs for course work
and research projects involving concurrent programming. It has been
used in concurrent programming courses to reinforce concepts with
small programming projects and with larger projects such as replicated
databases, distributed simulations, and parts of distributed operating
systems such as file systems and command interpreters. SR has also
been used as a tool in several masters theses and to implement larger
systems such as a system for mixed language programming, one for
distributed implementation of graph algorithms, experiments with load
balancing algorithms, and experiments with upcall program structures.
SR now runs on any of these machines:
Vax (BSD Unix, or Ultrix with gcc)
Sun 2, Sun 3, or Sun 4
Decstation 3100
NeXT
Hewlett Packard 9000 (series 300 and 800)
Encore Multimax (Umax)
An SR program runs on one or more networked machines of the same architecture.
SR is available by anonymous FTP from Arizona.EDU (128.196.128.118 or
192.12.69.1). SR tar(1) files are available in the sr subdirectory;
be sure to transfer files in binary (image) mode. The files are:
sr.tar The SR programming language, including source code,
documentation, checkout programs, and examples.
vs.tar Extended verification suite, needed only if you're going to
modify the system or port it to a new architecture.
The same files are also available in compress(1) form as sr.tar.Z and vs.tar.Z.
If you pick up a copy of SR by FTP, please let us know by email to
"sr-project@Arizona.EDU". This address can also be used for any questions or
comments. Via uucp, you can reach us at uunet!arizona!sr-project.
SR is available by mail on 1/2" magnetic tape or 1/4" Sun cartridge. For
details and an order blank, contact the SR project at the email address above;
or call (602) 621-2018; or send a letter to:
SR Project
Department of Computer Science
University of Arizona
Tucson, AZ 85721
An electronic mailing list is in place for discussing SR topics. You can
join by sending your email address to "info-sr-request@Arizona.EDU".
From gmt Thu Jul 27 10:28:47 1989
Date: Thu, 27 Jul 89 10:28:47 MST
From: "Gregg Townsend" <gmt>
Message-Id: <8907271728.AA06740@megaron.arizona.edu>
Received: by megaron.arizona.edu (5.59-1.7/15)
id AA06740; Thu, 27 Jul 89 10:28:47 MST
To: info-sr
Subject: SR 1.1 release notes
Release Notes for SR Version 1.1
Gregg Townsend
Department of Computer Science
The University of Arizona
July 24, 1989
This document surveys the changes introduced between
Version 1.0 and Version 1.1 of the SR Programming Language.
The revised language is described more precisely in the
reference manual.
New Platforms
SR now supports a wider variety of system architec-
tures. New systems include the Decstation 3100, the Sun 4,
the NeXT computer system, and the Hewlett-Packard 9000
(series 300 and 800). SR can now also run on Vax Ultrix
systems if the GNU C compiler is available. As a result of
the modifications these systems required, additional ports
should be considerably easier.
Incompatible Language Changes
Signatures. Scalars are no longer considered compati-
ble with arrays, even if the size is the same. For example,
an integer vector of length 1 is no longer interchangeable
with a simple integer. The new restriction is partially
enforced at this time and we anticipate stricter checking in
the future.
Character Literals. Single quotes now designate a
character literal instead of a string literal. Double
quotes still define a string literal. A character literal
has type char and contains only one character. For example,
'x' and '\n' are character literals, while "x\n" is still a
string literal.
String literals must be replaced by character literals
in certain situations. A string can no longer be assigned
to a simple char variable nor passed as an argument to the
char() conversion function, so
var c : char := "X"
var z[3] : char := ([3] char("z"))
become
var c : char := 'X'
var z[3] : char := ([3] 'z')
Language Extensions
Operation Declarations. For consistency with other
declarations, the syntax for operation declarations has been
extended. The forms op a, b, c: optypename and op x(...),
y(...), z(...) are now accepted.
Semaphores. A new sem keyword allows explicit declara-
tion of semaphores. New P(name) and V(name) builtins are
also provided. These abbreviations provide no new facili-
ties but sometimes allow a clearer expression of the
programmer's intentions. Diagnostics are still in terms of
the underlying implementation as special operations.
Processes. SR now allows the specification of quantif-
iers when declaring processes, for example process p (i:=1
to 3) declares an array of processes.
Co Statements. A send statement is now allowed as the
invocation part of a co statement.
Input Statements. An else clause is now allowed, and
will be executed if no invocation is selectable. st is now
allowed as an alternative to and for introducing a synchron-
ization expression.
Pointers. Pointer arithmetic, similar to that of C,
has been added. Pointers can now be printed using write and
writes. A generic pointer type ptr any has been added.
New Timing Functions. age() returns the elapsed time
since creation of the current virtual machine. nap(msec)
suspends the current SR process for a specified interval.
Commands and Tools
srl now accepts .a files as command arguments to allow
linking with user libraries of C functions.
srl no longer creates a re-srl file. The re-srl file
caused more confusion than it was worth.
srm has a new -s option to produce a smarter Makefile.
srgrind is a new script that uses vgrind to format SR
code for troff.
An SR editing mode for GNU Emacs is now provided.
Internal Improvements
Numerous bugs, notably some involving virtual machines,
have been fixed.
I/O waiting is handled much more intelligently, and
periodic timer interrupts are no longer used. Among other
things, these changes improve the performance of multiple-
virtual-machine programs.
Code has been added to prevent a process in a CPU loop
from shutting out all others.
Smarter code generation has improved the performance of
in statements.
Documentation and Examples
The updated reference manual, Report on the SR Program-
ming Language, Version 1.1, is included. The installation
guide and other documents were also revised. The porting
guide was completely rewritten.
PostScript versions of the documentation are now
included in the distribution.
Some new programs have been added in the examples sub-
directory. One of these is a working version of the ``Din-
ing Philosophers'' program from the SR Overview.
Acknowledgements
Many of these changes are due the efforts of outside
contributors. In particular, we thank Ron Olsson, Carole
McNamee, John Wagner, and Greg Whitehead at the University
of California at Davis; and David Jacobson, Ulrike Glav-
itsch, Luigi Semenzato, and Joe Park at Hewlett-Packard.
From aprakash@dost.eecs.umich.edu Wed Aug 16 12:18:01 1989
Received: from dost.eecs.umich.edu by megaron.arizona.edu (5.59-1.7/15) via SMTP
id AA10381; Wed, 16 Aug 89 12:18:01 MST
Received: by dost.eecs.umich.edu (5.57/umich-5.5)
id AA02462; Wed, 16 Aug 89 15:07:23 EDT
Date: Wed, 16 Aug 89 15:07:23 EDT
From: aprakash@dost.eecs.umich.edu (Atul Prakash)
Message-Id: <8908161907.AA02462@dost.eecs.umich.edu>
To: info-sr@arizona.edu
Subject: Unexpected deadlock in dining philosopher code?
Cc: aprakash@dost.eecs.umich.edu
I was running the dining philosopher solution in examples/dining directory
with a slight modification on my DEC 3100 and it seems to run into
an unexpected deadlock. The only modification is to run the
program on multiple virtual machines, with each virtual machine
running one philosopher and one
servant. On completing the specified number of iterations, the philosophers
are supposed to print out a message "philosopher id wishes to end". On
most runs, this message is successfully printed out by each philosopher.
However, at times,
it is not and I have no explanation. As far as I can make out, the program
is not supposed to deadlock. I am a new user of SR and I want
to find out where the bug is -- in SR, in Ultrix, or in the program. Any
explanations for this behavior?
-- Atul Prakash
(aprakash@zip.eecs.umich.edu)
Here is the CODE I used followed by a SCRIPT of one of the sample runs:
--------- modified code for dining.sr -----------------------
## Distributed Dining Philosophers
# %W% %G%
#
# Based on the example in "An Overview of the SR Language and Implementation",
# by Greg Andrews, Ron Olsson, and a cast of thousands, in the January, 1988
# issue of TOPLAS (ACM Transactions on Programming Languages and Systems 10,1,
# 51-86).
#
# The algorithm is from Chandy and Misra's "Drinking Philosophers Problem",
# which appeared in the October, 1984, issue of TOPLAS (6,4, 632-646).
#
# usage: a.out n s (for n philosophers and s sessions)
# Abstract operations define two types of servant operations.
resource PhilOps # services provided to the philosopher
op getforks() {call}
op relforks()
end
resource ServOps # messages exchanged among servants
op needL() {send} # requests for a fork
op needR() {send}
op passL() {send} # passing a fork to a neighbor
op passR() {send}
end
# Servants do all the work. There's one for each philosopher.
resource Servant
extend PhilOps, ServOps
op links(l,r : cap ServOps) # init neighbor links
op forks(haveL, dirtyL, haveR, dirtyR : bool) # init fork values
body Servant(id : int)
var l, r : cap ServOps
var haveL, dirtyL, haveR, dirtyR : bool
op hungry() {send}
op eat() {send}
proc getforks()
write("philosopher", id, "is hungry")
send hungry() # let server know philosopher is hungry
receive eat() # wait for permission to eat
end
process server
receive links(l,r)
receive forks(haveL,dirtyL,haveR,dirtyR)
write("servant",id,"is executing")
do true->
in hungry() ->
# ask for forks I do not have -- note: I ask my right
# neighbor for his left fork, and my left neighbor for
# his right fork
if ~haveR -> send r.needL() fi
if ~haveL -> send l.needR() fi
# wait until I have both forks
do ~(haveL & haveR) ->
in passL() -> haveL := true; dirtyL := false
[] passR() -> haveR := true; dirtyR := false
[] needR() & dirtyR ->
haveR := false; dirtyR := false
send r.passL()
[] needL() & dirtyL ->
haveL := false; dirtyL := false
send l.passR()
ni
od
# let my philosopher eat; wait for him to finish
send eat(); dirtyL := true; dirtyR := true
receive relforks()
[] needR() ->
# right neighbor needs his left fork, which is my right fork
haveR := false; dirtyR := false
send r.passL()
[] needL() ->
# left neighbor needs his right fork, which is my left fork
haveL := false; dirtyL := false
send l.passR()
ni
od
end server
end Servant
# The Philosopher resource is simple.
resource Philosopher
import PhilOps
body Philosopher(myservant : cap PhilOps; id, t : int)
process phil
write("philosopher", id, "is beginning")
fa i := 1 to t ->
myservant.getforks()
write("philosopher",id,"is eating") # eat
myservant.relforks()
write("philosopher",id,"is thinking") # think
af
write("philosopher", id, "wishes to end")
end
end Philosopher
# The main resource starts everything up.
resource Main
import Philosopher, PhilOps, ServOps, Servant
body Main()
initial
var n := 5
var t := 3
getarg(1,n) # get number of philosophers, if specified
getarg(2,t) # get session count, if specified
var s[1:n] : cap Servant
var si[1:n] : cap ServOps
var pi[1:n] : cap PhilOps
var p[1:n] : cap Philosopher
var vmcap[1:n] : cap vm
# create five virtual machines, one for each servant and
# philosopher pair.
fa i := 1 to n ->
vmcap[i] := create vm() on 0
af
# create each servant and philosopher
fa i := 1 to n ->
s[i] := create Servant(i) on vmcap[1]
si[i].needL := s[i].needL # build ServantOp cap
si[i].needR := s[i].needR
si[i].passL := s[i].passL
si[i].passR := s[i].passR
pi[i].getforks := s[i].getforks # build PhilosopherOp cap
pi[i].relforks := s[i].relforks
p[i] := create Philosopher(pi[i],i,t) on vmcap[1]
af
# give each Servant its links to neighboring Servants
send s[1].links(si[n],si[2])
fa i := 2 to n-1 -> send s[i].links(si[i-1],si[i+1]) af
send s[n].links(si[n-1],si[1])
# initialize each Servant's forks
# note: this must be asymmetric or deadlock could result
send s[1].forks(true,false,true,false)
fa i := 2 to n-1 -> send s[i].forks(false,false,true,false) af
send s[n].forks(false,false,false,false)
end
end Main
------------------------ A script that ends in a deadlock -------------
% dining
philosopher 1 is beginning
philosopher 1 is hungry
philosopher 2 is beginning
philosopher 2 is hungry
philosopher 3 is beginning
philosopher 3 is hungry
philosopher 4 is beginning
philosopher 4 is hungry
philosopher 5 is beginning
philosopher 5 is hungry
servant 1 is executing
philosopher 1 is eating
servant 2 is executing
servant 3 is executing
philosopher 1 is thinking
philosopher 2 is eating
philosopher 1 is hungry
servant 4 is executing
philosopher 2 is thinking
philosopher 3 is eating
servant 5 is executing
philosopher 2 is hungry
philosopher 3 is thinking
philosopher 4 is eating
philosopher 3 is hungry
philosopher 4 is thinking
philosopher 5 is eating
philosopher 4 is hungry
philosopher 5 is thinking
philosopher 5 is hungry
---- All the processes hang at this point ------
From olsson@ivy.ucdavis.edu Wed Aug 16 17:28:06 1989
Received: from clover.ucdavis.edu by megaron.arizona.edu (5.59-1.7/15) via SMTP
id AA24595; Wed, 16 Aug 89 17:28:06 MST
Received: from ivy.ucdavis.edu by clover.ucdavis.edu (5.59/UCD.EECS.1.11)
id AA00566; Wed, 16 Aug 89 17:24:29 PDT
Received: by ivy.ucdavis.edu (3.2/3.14)
id AA11648; Wed, 16 Aug 89 16:35:07 PDT
Date: Wed, 16 Aug 89 16:35:07 PDT
From: olsson@ivy.ucdavis.edu (Ron Olsson)
Message-Id: <8908162335.AA11648@ivy.ucdavis.edu>
To: aprakash@dost.eecs.umich.edu, info-sr@arizona.edu
In-Reply-To: Atul Prakash's message of Wed, 16 Aug 89 15:07:23 EDT <8908161907.AA02462@dost.eecs.umich.edu>
Subject: Unexpected deadlock in dining philosopher code?
Date: Wed, 16 Aug 89 15:07:23 EDT
From: aprakash@dost.eecs.umich.edu (Atul Prakash)
I was running the dining philosopher solution in examples/dining
directory with a slight modification on my DEC 3100 and it seems to
run into an unexpected deadlock. The only modification is to run
the program on multiple virtual machines, with each virtual machine
running one philosopher and one servant. On completing the
specified number of iterations, the philosophers are supposed to
print out a message "philosopher id wishes to end". On most runs,
this message is successfully printed out by each philosopher.
However, at times, it is not and I have no explanation. As far as I
can make out, the program is not supposed to deadlock. I am a new
user of SR and I want to find out where the bug is -- in SR, in
Ultrix, or in the program. Any explanations for this behavior?
The problem is that the implementation of SR does not detect
deadlock/termination in multiple vm programs. Specifically, each
server on the different vm's blocks on its input statement; if our
implementation were smart, it would detect that the program is
quiescent and shut everything down.
The reason you get different output from different executions is that
some output is not being flushed. If you add a `flush(stdout)'
statement to the philosopher code right before its end, you'll get the
same output every time.
One way to modify the program so it halts is for each philosopher to
notify the main resource when it has finished; the main resource can
then execute a stop statement to terminate everything. I've attached
the modified program below. Let us know whether it works for you.
BTW, distributed deadlock/termination detection is on our Wishlist,
although it probably won't be implemented for at least 6 months.
(Thanks to Greg Andrews for recognizing the cause of this problem;
I'm answering since his machine is down.)
## Distributed Dining Philosophers
# %W% %G%
#
# Based on the example in "An Overview of the SR Language and Implementation",
# by Greg Andrews, Ron Olsson, and a cast of thousands, in the January, 1988
# issue of TOPLAS (ACM Transactions on Programming Languages and Systems 10,1,
# 51-86).
#
# The algorithm is from Chandy and Misra's "Drinking Philosophers Problem",
# which appeared in the October, 1984, issue of TOPLAS (6,4, 632-646).
#
# usage: a.out n s (for n philosophers and s sessions)
# Abstract operations define two types of servant operations.
resource PhilOps # services provided to the philosopher
op getforks() {call}
op relforks()
end
resource ServOps # messages exchanged among servants
op needL() {send} # requests for a fork
op needR() {send}
op passL() {send} # passing a fork to a neighbor
op passR() {send}
end
# Servants do all the work. There's one for each philosopher.
resource Servant
extend PhilOps, ServOps
op links(l,r : cap ServOps) # init neighbor links
op forks(haveL, dirtyL, haveR, dirtyR : bool) # init fork values
body Servant(id : int)
var l, r : cap ServOps
var haveL, dirtyL, haveR, dirtyR : bool
op hungry() {send}
op eat() {send}
proc getforks()
write("philosopher", id, "is hungry")
send hungry() # let server know philosopher is hungry
receive eat() # wait for permission to eat
end
process server
receive links(l,r)
receive forks(haveL,dirtyL,haveR,dirtyR)
write("servant",id,"is executing")
do true->
in hungry() ->
# ask for forks I do not have -- note: I ask my right
# neighbor for his left fork, and my left neighbor for
# his right fork
if ~haveR -> send r.needL() fi
if ~haveL -> send l.needR() fi
# wait until I have both forks
do ~(haveL & haveR) ->
in passL() -> haveL := true; dirtyL := false
[] passR() -> haveR := true; dirtyR := false
[] needR() & dirtyR ->
haveR := false; dirtyR := false
send r.passL()
[] needL() & dirtyL ->
haveL := false; dirtyL := false
send l.passR()
ni
od
# let my philosopher eat; wait for him to finish
send eat(); dirtyL := true; dirtyR := true
receive relforks()
[] needR() ->
# right neighbor needs his left fork, which is my right fork
haveR := false; dirtyR := false
send r.passL()
[] needL() ->
# left neighbor needs his right fork, which is my left fork
haveL := false; dirtyL := false
send l.passR()
ni
od
end server
end Servant
# The Philosopher resource is simple.
resource Philosopher
import PhilOps
body Philosopher(myservant : cap PhilOps; id, t : int; done: cap())
process phil
write("philosopher", id, "is beginning")
fa i := 1 to t ->
myservant.getforks()
write("philosopher",id,"is eating") # eat
myservant.relforks()
write("philosopher",id,"is thinking") # think
af
write("philosopher", id, "wishes to end")
send done()
end
end Philosopher
# The main resource starts everything up.
resource Main
import Philosopher, PhilOps, ServOps, Servant
body Main()
initial
var n := 5
var t := 3
getarg(1,n) # get number of philosophers, if specified
getarg(2,t) # get session count, if specified
var s[1:n] : cap Servant
var si[1:n] : cap ServOps
var pi[1:n] : cap PhilOps
var p[1:n] : cap Philosopher
var vmcap[1:n] : cap vm
op done()
# create five virtual machines, one for each servant and
# philosopher pair.
fa i := 1 to n ->
vmcap[i] := create vm() on 0
af
# create each servant and philosopher
fa i := 1 to n ->
s[i] := create Servant(i) on vmcap[1]
si[i].needL := s[i].needL # build ServantOp cap
si[i].needR := s[i].needR
si[i].passL := s[i].passL
si[i].passR := s[i].passR
pi[i].getforks := s[i].getforks # build PhilosopherOp cap
pi[i].relforks := s[i].relforks
p[i] := create Philosopher(pi[i],i,t,done) on vmcap[1]
af
# give each Servant its links to neighboring Servants
send s[1].links(si[n],si[2])
fa i := 2 to n-1 -> send s[i].links(si[i-1],si[i+1]) af
send s[n].links(si[n-1],si[1])
# initialize each Servant's forks
# note: this must be asymmetric or deadlock could result
send s[1].forks(true,false,true,false)
fa i := 2 to n-1 -> send s[i].forks(false,false,true,false) af
send s[n].forks(false,false,false,false)
# wait for philosophers to finish; then stop.
fa i := 1 to n -> receive done() af
stop
end
end Main
From aprakash@dost.eecs.umich.edu Thu Aug 17 08:30:51 1989
Received: from dost.eecs.umich.edu by megaron.arizona.edu (5.59-1.7/15) via SMTP
id AA06162; Thu, 17 Aug 89 08:30:51 MST
Received: by dost.eecs.umich.edu (5.57/umich-5.5)
id AA03332; Thu, 17 Aug 89 11:19:40 EDT
Message-Id: <8908171519.AA03332@dost.eecs.umich.edu>
To: olsson@ivy.ucdavis.edu (Ron Olsson)
Cc: aprakash@zip.eecs.umich.edu, info-sr@arizona.edu
Subject: Re: Unexpected deadlock in dining philosopher code?
In-Reply-To: Your message of Wed, 16 Aug 89 16:35:07 -0700.
<8908162335.AA11648@ivy.ucdavis.edu>
Date: Thu, 17 Aug 89 11:19:36 EDT
From: aprakash@dost.eecs.umich.edu
I get the "deadlock" problem even with the new code Ron Olsson sent recently
for multiple virtual machine version of dining philosophers with
termination detection.
I had also initially thought that lack of deadlock detection may be
the problem and had tried
fixing it unsuccesfully with termination detection earlier (I used a
less elegant solution though then Ron Olsson sent) but avoided
including it in my previous mail as it did not affect the problem.
You have to run the program several times in order to reproduce the
deadlock. On my machine (3100 running Ultrix), it occurs on
the average of once every five executions.
Below is the script from a correct run and an erroneous run
with Ron Olsson's code.
I think it blocks at pretty much the same point whether there is
termination detection or not.
-- Atul Prakash
(aprakash@zip.eecs.umich.edu)
-------------- script for correct execution -------------------------------
%dining
philosopher 5 is hungry
servant 1 is executing
philosopher 1 is eating
servant 2 is executing
servant 3 is executing
philosopher 1 is thinking
philosopher 2 is eating
philosopher 1 is hungry
servant 4 is executing
philosopher 2 is thinking
philosopher 3 is eating
philosopher 2 is hungry
servant 5 is executing
philosopher 3 is thinking
philosopher 4 is eating
philosopher 1 is eating
philosopher 3 is hungry
philosopher 4 is thinking
philosopher 1 is thinking
philosopher 5 is eating
philosopher 2 is eating
philosopher 4 is hungry
philosopher 1 is hungry
philosopher 5 is thinking
philosopher 2 is thinking
philosopher 3 is eating
philosopher 5 is hungry
philosopher 2 is hungry
philosopher 3 is thinking
philosopher 4 is eating
philosopher 1 is eating
philosopher 3 is hungry
philosopher 4 is thinking
philosopher 1 is thinking
philosopher 5 is eating
philosopher 2 is eating
philosopher 4 is hungry
philosopher 1 wishes to end
philosopher 5 is thinking
philosopher 2 is thinking
philosopher 3 is eating
philosopher 5 is hungry
philosopher 2 wishes to end
philosopher 3 is thinking
philosopher 4 is eating
philosopher 3 wishes to end
philosopher 4 is thinking
philosopher 5 is eating
philosopher 4 wishes to end
philosopher 5 is thinking
philosopher 5 wishes to end
The program successfully terminates here and you get the Unix prompt.
--------- script for incorrect execution
%dining
philosopher 1 is beginning
philosopher 1 is hungry
philosopher 2 is beginning
philosopher 2 is hungry
philosopher 3 is beginning
philosopher 3 is hungry
philosopher 4 is beginning
philosopher 4 is hungry
philosopher 5 is beginning
philosopher 5 is hungry
servant 1 is executing
philosopher 1 is eating
servant 2 is executing
servant 3 is executing
philosopher 1 is thinking
philosopher 2 is eating
philosopher 1 is hungry
servant 4 is executing
philosopher 2 is thinking
philosopher 3 is eating
servant 5 is executing
philosopher 2 is hungry
philosopher 3 is thinking
philosopher 4 is eating
philosopher 3 is hungry
philosopher 4 is thinking
philosopher 5 is eating
philosopher 4 is hungry
philosopher 5 is thinking
philosopher 5 is hungry
The program hangs here and has to be killed. Couple of things to notice
here for this run. First notice that everyone is supposed to eat three
times (the default); however, 1 has only once. So, we are not
at termination point. Further, at this point 5 is supposed to pass
its forks to 1 or 4 and so either 1 or 4 should be able to eat. However,
that is not happening.
From jacobson%cello@hplabs.hp.com Fri Aug 18 06:59:32 1989
Received: from hplms2.hpl.hp.com by megaron.arizona.edu (5.59-1.7/15) via SMTP
id AA06562; Fri, 18 Aug 89 06:59:32 MST
Received: from cello.HPL.HP.COM (cello.hpl.hp.com) by hplms2.hp.com; Fri, 18 Aug 89 06:55:57 pdt
Received: by cello.HPL.HP.COM; Thu, 17 Aug 89 21:08:30 pdt
Date: Thu, 17 Aug 89 21:08:30 pdt
From: David Jacobson <jacobson%cello@hplabs.hp.com>
Message-Id: <8908180408.AA10346@cello.HPL.HP.COM>
To: info-sr@arizona.edu, jacobson%cello@hplabs.hp.com
Subject: Dining philosopher problems
When I run the Ron Olssson's code for the philosophers on an HP
9000s800 (actually an 835) running HP-UX version 3.10 there are two
problems. After the first round where the philosophers begin, each
philosopher just runs in isolation. (This is running with the default
5 philosophers and 3 rounds.) In addition, about every 5 times or
so, it stops early, just terminating normally. (It does not need to
be killed as others have reported. A script of one such run follows.
-- David Jacobson
HP Labs
------------------------
philosopher 1 is beginning
philosopher 1 is hungry
philosopher 2 is beginning
philosopher 2 is hungry
philosopher 3 is beginning
philosopher 3 is hungry
philosopher 4 is beginning
philosopher 4 is hungry
philosopher 5 is beginning
philosopher 5 is hungry
servant 1 is executing
philosopher 1 is eating
philosopher 1 is thinking
philosopher 1 is hungry
philosopher 1 is eating
philosopher 1 is thinking
philosopher 1 is hungry
philosopher 1 is eating
philosopher 1 is thinking
philosopher 1 wishes to end
servant 2 is executing
philosopher 2 is eating
philosopher 2 is thinking
philosopher 2 is hungry
philosopher 2 is eating
philosopher 2 is thinking
philosopher 2 is hungry
philosopher 2 is eating
philosopher 2 is thinking
philosopher 2 wishes to end
servant 3 is executing
philosopher 3 is eating
philosopher 3 is thinking
philosopher 3 is hungry
philosopher 3 is eating
philosopher 3 is thinking
philosopher 3 is hungry
philosopher 3 is eating
philosopher 3 is thinking
philosopher 3 wishes to end
servant 4 is executing
From deng@chaos.sunysb.edu Fri Aug 18 07:16:04 1989
Received: from chaos.sunysb.edu by megaron.arizona.edu (5.59-1.7/15) via SMTP
id AA07389; Fri, 18 Aug 89 07:16:04 MST
Received: by chaos.sunysb.edu (3.2/25-eef)
id AA05156; Fri, 18 Aug 89 10:04:26 EDT
Date: Fri, 18 Aug 89 10:04:26 EDT
From: Yuefan Deng <deng@chaos.sunysb.edu>
Message-Id: <8908181404.AA05156@chaos.sunysb.edu>
To: info-sr@arizona.edu, jacobson%cello@hplabs.hp.com
Subject: Re: Dining philosopher problems
Could you all change my address from deng@cmcl2.nyu.edu to
deng@chaos.sunysb.edu. Thanks in advance.
y deng
From jacobson%cello@hplabs.hp.com Fri Aug 18 09:21:31 1989
Received: from hplms2.hpl.hp.com by megaron.arizona.edu (5.59-1.7/15) via SMTP
id AA14754; Fri, 18 Aug 89 09:21:31 MST
Received: from cello.HPL.HP.COM (cello.hpl.hp.com) by hplms2.hp.com; Fri, 18 Aug 89 09:17:50 pdt
Received: by cello.HPL.HP.COM; Fri, 18 Aug 89 09:17:31 pdt
Date: Fri, 18 Aug 89 09:17:31 pdt
From: David Jacobson <jacobson%cello@hplabs.hp.com>
Message-Id: <8908181617.AA18157@cello.HPL.HP.COM>
To: info-sr@arizona.edu
Cc: jacobson%cello@hplabs.hp.com
Subject: Dining philosophers
I added a little bit of code to the loop that collects the done
messages to print out which philosopher was done. Now on an
HP9000s800 the philosophers proceed somewhat irregularly, instead of
philosopher 1 eating all 3 times, then philosopher 2, etc. Observe
the new code at the end. (See below for 2 more statements that were
added, though.)
However, sometimes I got a deadlock in which all 5 philosopher's are
hungry. (A script follows.) I traced the problem to a bug in the sr
code for the servant. When a philosopher is hungry, her servant is
willing to yield a dirty fork to a neighboring servant. The servant
should ask for it back, though, and the code forgot to do that.
I've added calls to needL and needR, as shown in the code at the end.
(They were not there in the code that generated the log shown below.)
Now things seem to work ok. (We still have the bug mentioned in my
previous message, though.)
-- David Jacobson
---------------------------------
This log code comes from a revision of Ron Olsson's code with an added write
statement in the collector of the done messages to identify the philosopher
that is done.
philosopher 1 is beginning
philosopher 1 is hungry
philosopher 2 is beginning
philosopher 2 is hungry
philosopher 3 is beginning
philosopher 3 is hungry
philosopher 4 is beginning
philosopher 4 is hungry
philosopher 5 is beginning
philosopher 5 is hungry
servant 1 is executing
philosopher 1 is eating
servant 2 is executing
servant 3 is executing
philosopher 1 is thinking
philosopher 2 is eating
philosopher 1 is hungry
servant 4 is executing
philosopher 2 is thinking
philosopher 3 is eating
servant 5 is executing
philosopher 2 is hungry
philosopher 3 is thinking
philosopher 4 is eating
philosopher 3 is hungry
philosopher 4 is thinking
philosopher 5 is eating
philosopher 4 is hungry
philosopher 5 is thinking
philosopher 5 is hungry
The program hung at this point and had to be killed.
---------------------------------------
## Distributed Dining Philosophers
# %W% %G%
#
# Based on the example in "An Overview of the SR Language and Implementation",
# by Greg Andrews, Ron Olsson, and a cast of thousands, in the January, 1988
# issue of TOPLAS (ACM Transactions on Programming Languages and Systems 10,1,
# 51-86).
#
# The algorithm is from Chandy and Misra's "Drinking Philosophers Problem",
# which appeared in the October, 1984, issue of TOPLAS (6,4, 632-646).
#
# usage: a.out n s (for n philosophers and s sessions)
# Abstract operations define two types of servant operations.
resource PhilOps # services provided to the philosopher
op getforks() {call}
op relforks()
end
resource ServOps # messages exchanged among servants
op needL() {send} # requests for a fork
op needR() {send}
op passL() {send} # passing a fork to a neighbor
op passR() {send}
end
# Servants do all the work. There's one for each philosopher.
resource Servant
extend PhilOps, ServOps
op links(l,r : cap ServOps) # init neighbor links
op forks(haveL, dirtyL, haveR, dirtyR : bool) # init fork values
body Servant(id : int)
var l, r : cap ServOps
var haveL, dirtyL, haveR, dirtyR : bool
op hungry() {send}
op eat() {send}
proc getforks()
write("philosopher", id, "is hungry")
send hungry() # let server know philosopher is hungry
receive eat() # wait for permission to eat
end
process server
receive links(l,r)
receive forks(haveL,dirtyL,haveR,dirtyR)
write("servant",id,"is executing")
do true->
in hungry() ->
# ask for forks I do not have -- note: I ask my right
# neighbor for his left fork, and my left neighbor for
# his right fork
if ~haveR -> send r.needL() fi
if ~haveL -> send l.needR() fi
# wait until I have both forks
do ~(haveL & haveR) ->
in passL() -> haveL := true; dirtyL := false
[] passR() -> haveR := true; dirtyR := false
[] needR() & dirtyR ->
haveR := false; dirtyR := false
send r.passL()
send r.needL() # ask for fork back
[] needL() & dirtyL ->
haveL := false; dirtyL := false
send l.passR()
send l.needR() # ask for fork back
ni
od
# let my philosopher eat; wait for him to finish
send eat(); dirtyL := true; dirtyR := true
receive relforks()
[] needR() ->
# right neighbor needs his left fork, which is my right fork
haveR := false; dirtyR := false
send r.passL()
[] needL() ->
# left neighbor needs his right fork, which is my left fork
haveL := false; dirtyL := false
send l.passR()
ni
od
end server
end Servant
# The Philosopher resource is simple.
resource Philosopher
import PhilOps
body Philosopher(myservant : cap PhilOps; id, t : int; done: cap(n : int))
process phil
write("philosopher", id, "is beginning")
fa i := 1 to t ->
myservant.getforks()
write("philosopher",id,"is eating") # eat
myservant.relforks()
write("philosopher",id,"is thinking") # think
af
write("philosopher", id, "wishes to end")
send done(id)
end
end Philosopher
# The main resource starts everything up.
resource Main
import Philosopher, PhilOps, ServOps, Servant
body Main()
initial
var n := 5
var t := 3
getarg(1,n) # get number of philosophers, if specified
getarg(2,t) # get session count, if specified
var s[1:n] : cap Servant
var si[1:n] : cap ServOps
var pi[1:n] : cap PhilOps
var p[1:n] : cap Philosopher
var vmcap[1:n] : cap vm
op done(n:int)
var j : int
# create five virtual machines, one for each servant and
# philosopher pair.
fa i := 1 to n ->
vmcap[i] := create vm() on 0
af
# create each servant and philosopher
fa i := 1 to n ->
s[i] := create Servant(i) on vmcap[1]
si[i].needL := s[i].needL # build ServantOp cap
si[i].needR := s[i].needR
si[i].passL := s[i].passL
si[i].passR := s[i].passR
pi[i].getforks := s[i].getforks # build PhilosopherOp cap
pi[i].relforks := s[i].relforks
p[i] := create Philosopher(pi[i],i,t,done) on vmcap[1]
af
# give each Servant its links to neighboring Servants
send s[1].links(si[n],si[2])
fa i := 2 to n-1 -> send s[i].links(si[i-1],si[i+1]) af
send s[n].links(si[n-1],si[1])
# initialize each Servant's forks
# note: this must be asymmetric or deadlock could result
send s[1].forks(true,false,true,false)
fa i := 2 to n-1 -> send s[i].forks(false,false,true,false) af
send s[n].forks(false,false,false,false)
# wait for philosophers to finish; then stop.
fa i := 1 to n ->
receive done(j)
write("Recvd done from philosopher ",j)
af
stop
end
end Main
From olsson@ivy.ucdavis.edu Fri Aug 18 10:28:00 1989
Received: from clover.ucdavis.edu by megaron.arizona.edu (5.59-1.7/15) via SMTP
id AA20365; Fri, 18 Aug 89 10:28:00 MST
Received: from ivy.ucdavis.edu by clover.ucdavis.edu (5.59/UCD.EECS.1.11)
id AA12493; Fri, 18 Aug 89 10:24:00 PDT
Received: by ivy.ucdavis.edu (3.2/3.14)
id AA16450; Fri, 18 Aug 89 10:23:24 PDT
Date: Fri, 18 Aug 89 10:23:24 PDT
From: olsson@ivy.ucdavis.edu (Ron Olsson)
Message-Id: <8908181723.AA16450@ivy.ucdavis.edu>
To: jacobson%cello@hplabs.hp.com, info-sr@arizona.edu
In-Reply-To: David Jacobson's message of Fri, 18 Aug 89 09:17:31 pdt <8908181617.AA18157@cello.HPL.HP.COM>
Subject: Dining philosophers
Yes, the code in examples/dining has the bug you describe. The
overview paper has it right, but we lost something in the translation.
Thanks for finding that.
From gmt Fri Aug 18 15:14:36 1989
Date: Fri, 18 Aug 89 15:14:36 MST
From: "Gregg Townsend" <gmt>
Message-Id: <8908182214.AA08300@megaron.arizona.edu>
Received: by megaron.arizona.edu (5.59-1.7/15)
id AA08300; Fri, 18 Aug 89 15:14:36 MST
To: info-sr
Subject: SR under Vax Ultrix 3.1
We have found that SR Version 1.1 builds and runs properly under Vax Ultrix
version 3.1 using the standard C compiler, cc.
This contrasts with Ultrix version 2, where cc couldn't handle SR, and so
the use of gcc was required. Now, nothing special is needed.
Gregg Townsend / Computer Science Dept / Univ of Arizona / Tucson, AZ 85721
+1 602 621 4325 gmt@Arizona.EDU 110 57 16 W / 32 13 45 N / +758m
From aprakash@dost.eecs.umich.edu Mon Aug 21 07:43:27 1989
Received: from dost.eecs.umich.edu by megaron.arizona.edu (5.59-1.7/15) via SMTP
id AA20868; Mon, 21 Aug 89 07:43:27 MST
Received: by dost.eecs.umich.edu (5.57/umich-5.5)
id AA05035; Mon, 21 Aug 89 10:32:16 EDT
Message-Id: <8908211432.AA05035@dost.eecs.umich.edu>
To: olsson@ivy.ucdavis.edu (Ron Olsson)
Cc: jacobson%cello@hplabs.hp.com, info-sr@arizona.edu
Subject: Re: Dining philosophers
In-Reply-To: Your message of Fri, 18 Aug 89 10:23:24 -0700.
<8908181723.AA16450@ivy.ucdavis.edu>
Date: Mon, 21 Aug 89 10:32:13 EDT
From: aprakash@dost.eecs.umich.edu
You are welcome. It will be interesting to see what the bug is.
Incidently, that raises a larger question of how does one go about debugging
a program in SR, based on program translation to a different language?
Debugging multiple virtual machine programs is hard with dbx even for
programs written in C, but can -g option with dbx be somehow
used (with some manual mapping of SR names to C names, etc.) in
stepping through a single virtual machine SR program via a debugger? This
technique was used quite successfully earlier for C++ programs that
were translated to C (before C++ debuggers became available).
-- Atul
(aprakash@zip.eecs.umich.edu)
From jacobson%cello@hplabs.hp.com Fri Aug 25 09:58:10 1989
Received: from hplms2.hpl.hp.com by megaron.arizona.edu (5.59-1.7/15) via SMTP
id AA10959; Fri, 25 Aug 89 09:58:10 MST
Received: from cello.HPL.HP.COM (cello.hpl.hp.com) by hplms2.hp.com; Fri, 25 Aug 89 08:36:20 pdt
Received: by cello.HPL.HP.COM; Fri, 25 Aug 89 08:36:16 pdt
Date: Fri, 25 Aug 89 08:36:16 pdt
From: David Jacobson <jacobson%cello@hplabs.hp.com>
Message-Id: <8908251536.AA27066@cello.HPL.HP.COM>
To: info-sr@arizona.edu
Subject: Circular importation in resource specs.
There are a number of times when I have two resources that need to
import each other's specs. For example, there might be a dictionary
resource that exports operations for mapping strings to capabilities
for foo_servers. Foo_servers export an operation that returns
capabilies for dictionaries.
The obvious specs are these
resource dictionary
import foo_server
op insert(key:string(*);value cap foo_server)
op lookup(key:string(*)) returns value cap_fooserver
end
resource foo_server
import dictionary
op mumble() returns x:cap dictionary
end
However, SR does not like circularity of importation. Does anyone out
there have any suggestions about how to get around this problem?
-- David Jacobson
From greg Fri Aug 25 14:29:16 1989
Received: from paloverde.arizona.edu by megaron.arizona.edu (5.59-1.7/15) via SMTP
id AA27982; Fri, 25 Aug 89 14:29:16 MST
Date: Fri, 25 Aug 89 14:29:11 MST
From: "Greg Andrews" <greg>
Message-Id: <8908252129.AA05094@paloverde.arizona.edu>
Received: by paloverde.arizona.edu; Fri, 25 Aug 89 14:29:11 MST
In-Reply-To: <8908251536.AA27066@cello.HPL.HP.COM>
To: info-sr@arizona.edu, jacobson%cello@hplabs.hp.com
Subject: Re: Circular importation in resource specs.
From: David Jacobson <jacobson%cello@hplabs.hp.com>
To: info-sr@arizona.edu
Subject: Circular importation in resource specs.
There are a number of times when I have two resources that need to
import each other's specs. For example, there might be a dictionary
resource that exports operations for mapping strings to capabilities
for foo_servers. Foo_servers export an operation that returns
capabilies for dictionaries.
The obvious specs are these
resource dictionary
import foo_server
op insert(key:string(*);value cap foo_server)
op lookup(key:string(*)) returns value cap_fooserver
end
resource foo_server
import dictionary
op mumble() returns x:cap dictionary
end
However, SR does not like circularity of importation. Does anyone out
there have any suggestions about how to get around this problem?
-- David Jacobson
Lots of students ask the same question! There are two solutions.
If there are just a few operations that one resource needs from
the other, put optype declarations in a global that both
resources import and have caps for the appropriate optypes.
The resources then talk to each other to get the capabilities
bound to the appropriate operations. Better yet, have a third
resource create both the dictionary and foo_server, then have
it give each the appropriate operation capabilities for the other.
The second approach is to use abstract resources to encapsulate
the subset of operations of dictionary and foo_server that the
other needs. These are compiled before the concrete resources,
which can then import the abstract resources and have caps for them.
Getting caps bound to the actual operations is done as above,
typically by a third resource. See the on-line decentralized
dining philosophers program for an example.
Because many people would like mutual imports, we are going to
bite the implementation bullet and allow it in Version 2.0
of SR, which we are starting to work on. That version won't
be available for about a year, though, since we several other
language extensions in mind and are just getting started.
-- Greg Andrews
From jacobson%cello@hplabs.hp.com Fri Aug 25 15:10:52 1989
Received: from hplms2.hpl.hp.com by megaron.arizona.edu (5.59-1.7/15) via SMTP
id AA01086; Fri, 25 Aug 89 15:10:52 MST
Received: from cello.HPL.HP.COM (cello.hpl.hp.com) by hplms2.hp.com; Fri, 25 Aug 89 15:07:15 pdt
Received: from localhost by cello.HPL.HP.COM; Fri, 25 Aug 89 15:07:12 pdt
To: "Greg Andrews" <greg@arizona.edu>
Cc: info-sr@arizona.edu
Subject: Re: Circular importation in resource specs.
In-Reply-To: Your message of "Fri, 25 Aug 89 14:29:11 MST."
<8908252129.AA05094@paloverde.arizona.edu>
Date: Fri, 25 Aug 89 15:07:10 PDT
Message-Id: <28744.620086030@cello>
From: jacobson%cello@hplabs.hp.com
Thank you for your reply to my query. But I think you answered a
slightly different question than I asked.
In my example, the caps are for entire resources. (I'm trying to use
resources as abstract data types. So a cap is is used to name an
instance of the ADT.) You have described how to pass capabilities for
*operations* around. Note that the dining philosophers solutions
passes around capabilities for things like needL, needR, passL, passR,
getforks, and relforks that are operations that take no parameters and
return no results -- in particular no capabilities for resources.
The only solution that I can see is to have a combined common abstract
type, dict_foo, then, branching two ways, extend and implement it.
resource dict_foo
# dictionary ops
op insert(key:string(*);value cap dict_foo)
op lookup(key:string(*)) returns value cap dict_foo
# foo_server ops
op mumble () returns x cap dict_foo
end
resource dictionary
extend dict_foo
body dictionary()
# instance data
proc insert ...
proc lookup ...
proc mumble()
write(stderr,"This is really a dictionary, you shouldn't call mumble")
stop
end
end
# and similarly for foo_server
-- David Jacobson
From greg Fri Aug 25 15:41:13 1989
Received: from paloverde.arizona.edu by megaron.arizona.edu (5.59-1.7/15) via SMTP
id AA02874; Fri, 25 Aug 89 15:41:13 MST
Date: Fri, 25 Aug 89 15:41:06 MST
From: "Greg Andrews" <greg>
Message-Id: <8908252241.AA05330@paloverde.arizona.edu>
Received: by paloverde.arizona.edu; Fri, 25 Aug 89 15:41:06 MST
In-Reply-To: <28744.620086030@cello>
To: greg@arizona.edu, jacobson%cello@hplabs.hp.com
Subject: Re: Circular importation in resource specs.
Cc: info-sr@arizona.edu
David is correct in his comments and shows how to
program around the lack of mutual imports. As I
said earlier, we will eventually support mutual import
to simplify the kind of mutual resource interaction
David described.
From csc319@computing.lancaster.ac.uk Mon Oct 9 12:27:15 1989
Received: from rvax.ccit.arizona.edu by megaron.arizona.edu (5.59-1.7/15) via SMTP
id AA11528; Mon, 9 Oct 89 12:27:15 MST
Received: from UKACRL.BITNET by rvax.ccit.arizona.edu; Mon, 9 Oct 89 11:59 MST
Received: from RL.IB by UKACRL.BITNET (Mailer X1.25) with BSMTP id 5243; Mon,
09 Oct 89 16:37:07 BST
Date: Mon, 9 Oct 89 15:37:59 GMT
From: csc319@computing.lancaster.ac.uk
Subject: Change of Address
To: info-sr@arizona.edu
Via: UK.AC.LANCS.COMP; 9 OCT 89 16:37:02 BST
Message-Id: <9299.8910091537@dcl-ugrad.comp.lancs.ac.uk>
Please could you change my mail address from:
csc220@comp.lancs.ac.uk.
to:
csc319@comp.lancs.ac.uk.
Thanks
Graham (Dean)
From djones%awesome.Berkeley.EDU@ucbvax.Berkeley.EDU Wed Oct 11 18:55:22 1989
Received: from ucbvax.Berkeley.EDU by megaron.arizona.edu (5.59-1.7/15) via SMTP
id AA08298; Wed, 11 Oct 89 18:55:22 MST
Received: from awesome.Berkeley.EDU by ucbvax.Berkeley.EDU (5.61/1.37)
id AA02634; Wed, 11 Oct 89 18:55:12 -0700
Received: from localhost by awesome.berkeley.edu (4.0/SMI-4.0)
id AA11305; Wed, 11 Oct 89 18:56:50 PDT
Message-Id: <8910120156.AA11305@awesome.berkeley.edu>
To: info-sr@arizona.edu
Subject: novice question
Date: Wed, 11 Oct 89 18:56:48 -0700
From: djones%awesome.Berkeley.EDU@ucbvax.Berkeley.EDU
I just installed SR on our SUNs and the first program I've tried,
aside from existing examples, has me quite befuddled.
What I want to do is create a "master" on the local SUN, and start
a "slave" on each SUN named on the command line. The "slaves" do
some trivial computation and then report to the "master" that
they are done. The "master" waits for everyone to report back and
then stops.
The file "remote.sr" is at the end of this message. Here is what
happens.
% srm
% make
sr -c remote.sr
srl -o a.out master slave main
% a.out awesome totally
Slaves will be on:
awesome
totally
makeslaves active
makemaster active
I am the master 2 slaves!
waiting ...
RTS warning: 3 blocked process during termination
%
It would appear that none of the sends or receives succeed.
Any suggestions?
thanks,
David Jones
djones@awesome.berkeley.edu
----------- cut here ------------------
resource master
op handshake(id:int)
body master(n:int)
initial
var num :int
write("I am the master of ",n," slaves!")
fa i:=1 to n ->
write("waiting ...")
flush(stdout)
receive handshake(num)
write("slave ",num," is done")
af
write("everyone is done.")
flush(stdout)
stop
end
end master
resource slave
import master
op number() returns n:int
body slave(m:cap master)
external gethostname(res s:string(*); namelen:int)
var h :string(64)
var myid :int
initial
gethostname(h,maxlength(h))
myid:=mymachine()
end
process v
writes("Slave on host ",h," running.\n")
flush(stdout)
nap(1000)
write("Slave on host ",h," done.\n")
flush(stdout)
send m.handshake(myid)
end
proc number() returns n
n:=myid
write("slave.number(",n,")")
flush(stdout)
end number
end slave
resource main
import master
import slave
op who_is_master(m:cap master) {send}
body main()
var n :int
initial
var s :string(100)
n:=numargs()
write("Slaves will be on: ")
fa i:=1 to n ->
getarg(i,s)
write(s)
af
flush(stdout)
end
process makeslaves
var s :string(100)
var remote :cap vm
var mastercap :cap master
var slavecap[1:n] :cap slave
write("makeslaves active")
flush(stdout)
receive who_is_master(mastercap)
write("about to create slaves\n")
flush(stdout)
fa i := 1 to n ->
getarg(i,s)
locate(i,s)
remote:=create vm() on i
if (remote = null) ->
write(stderr,"can't create vm on",s,"\n")
flush(stderr)
[] else ->
write("creating slave on ",s,"\n")
flush(stdout)
slavecap[i]:=create slave(mastercap) on remote
if (slavecap[i] = null) ->
write("create slave on host ",s,", machine ",i," failed.\n")
flush(stdout)
[] else ->
write("slave ",i," has machine id ",slavecap[i].number())
flush(stdout)
fi
fi
af
write("all slaves created")
flush(stdout)
nap(30000)
end makeslaves
process makemaster
var mastercap : cap master
write("makemaster active\n")
flush(stdout)
mastercap:=create master(n) on myvm()
if (mastercap = null) ->
write("failed to create a master\n")
flush(stdout)
stop
fi
write("master created\n")
flush(stdout)
send who_is_master(mastercap)
end makemaster
end main
From olsson@ivy.ucdavis.edu Wed Oct 11 20:59:20 1989
Received: from clover.ucdavis.edu by megaron.arizona.edu (5.59-1.7/15) via SMTP
id AA13131; Wed, 11 Oct 89 20:59:20 MST
Received: from ivy.ucdavis.edu by clover.ucdavis.edu (5.59/UCD.EECS.1.11)
id AA11806; Wed, 11 Oct 89 21:01:30 PDT
Received: by ivy.ucdavis.edu (3.2/3.14)
id AA15487; Wed, 11 Oct 89 20:58:14 PDT
Date: Wed, 11 Oct 89 20:58:14 PDT
From: olsson@ivy.ucdavis.edu (Ron Olsson)
Message-Id: <8910120358.AA15487@ivy.ucdavis.edu>
To: djones%awesome.Berkeley.EDU@ucbvax.Berkeley.EDU
Cc: info-sr@arizona.edu
In-Reply-To: djones%awesome.Berkeley.EDU@ucbvax.Berkeley.EDU's message of Wed, 11 Oct 89 18:56:48 -0700 <8910120156.AA11305@awesome.berkeley.edu>
Subject: novice question
Date: Wed, 11 Oct 89 18:56:48 -0700
From: djones%awesome.Berkeley.EDU@ucbvax.Berkeley.EDU
I just installed SR on our SUNs and the first program I've tried,
aside from existing examples, has me quite befuddled.
...
It would appear that none of the sends or receives succeed.
The problem is simple. main creates master by
mastercap:=create master(n) on myvm()
Recall, however, that a create statement doesn't terminate until the
initial code in the resource instance it is creating completes. The
essence of that code is
initial
fa i:=1 to n ->
receive handshake(num)
af
write("everyone is done.")
stop
end
But n>=1 and no slaves exist to send the master any handshakes, so
master hangs on the receive, thereby causing main to hang. (The
reason no servants exist is that main's create statement has not yet
terminated, so main hasn't created the servants.)
Two easy fixes:
(1) change initial in master to be a process. Then, master's initial
code is empty (except the implicit send to create that new process),
which terminates, allowing the create to terminate.
or (2) put a reply in master's initial. I.e.,
initial
reply # **** allower creator to continue
fa i:=1 to n ->
receive handshake(num)
af
write("everyone is done.")
stop
end
I think (1) is clearer.
BTW, not such a novice problem. I do this myself sometimes, and I've
seen a number of other people do the same. We should put it on our
common problem list.
From mcnamee@iris.ucdavis.edu Thu Oct 12 11:21:39 1989
Received: from clover.ucdavis.edu by megaron (5.59-1.7/15) via SMTP
id AA19609; Thu, 12 Oct 89 11:21:39 MST
Received: from iris.ucdavis.edu by clover.ucdavis.edu (5.59/UCD.EECS.1.11)
id AA16179; Thu, 12 Oct 89 11:23:42 PDT
Received: by iris (5.57/3.14)
id AA19802; Thu, 12 Oct 89 11:20:48 PDT
Date: Thu, 12 Oct 89 11:20:48 PDT
From: mcnamee@iris.ucdavis.edu (Carole McNamee)
Message-Id: <8910121820.AA19802@iris>
To: info-sr@arizona.edu
Subject: random number generator
Does anyone have an SR random number generator that produces "reasonable
sequences" ?
Thanks
C. McNamee
From gmt Thu Oct 12 17:48:24 1989
Date: Thu, 12 Oct 89 17:48:24 MST
From: "Gregg Townsend" <gmt>
Message-Id: <8910130048.AA14749@megaron.arizona.edu>
Received: by megaron.arizona.edu (5.59-1.7/15)
id AA14749; Thu, 12 Oct 89 17:48:24 MST
In-Reply-To: <8910121820.AA19802@iris>
To: mcnamee@iris.ucdavis.edu
Subject: Re: random number generator
Cc: info-sr
From: mcnamee@iris.ucdavis.edu (Carole McNamee)
Date: Thu, 12 Oct 89 11:20:48 PDT
Does anyone have an SR random number generator that produces
"reasonable sequences" ?
If you're just looking to obtain random numbers in an SR program,
the easiest thing is to call the C library. For example:
resource x ()
external getpid () returns n: int
external random () returns n: int
external srandom (seed: int)
initial
srandom(getpid())
fa i := 1 to 10 -> write(random()) af
end
end
From mcnamee@iris.ucdavis.edu Fri Oct 13 13:50:43 1989
Received: from clover.ucdavis.edu by megaron.arizona.edu (5.59-1.7/15) via SMTP
id AA20715; Fri, 13 Oct 89 13:50:43 MST
Received: from iris.ucdavis.edu by clover.ucdavis.edu (5.59/UCD.EECS.1.11)
id AA23715; Fri, 13 Oct 89 13:52:59 PDT
Received: by iris (5.57/3.14)
id AA16577; Fri, 13 Oct 89 11:58:25 PDT
Date: Fri, 13 Oct 89 11:58:25 PDT
From: mcnamee@iris.ucdavis.edu (Carole McNamee)
Message-Id: <8910131858.AA16577@iris>
To: gmt@arizona.edu, mcnamee@iris.ucdavis.edu
Subject: Re: random number generator
Cc: info-sr@arizona.edu
Thanks for your response, unfortunately my question wasn't specific enough.
I need to be able to control the seed as I would like many processes to be
able to call the generator and I would like to guarrantee that each process
gets the same sequence each time it executes.
From djones%awesome.Berkeley.EDU@ucbvax.Berkeley.EDU Tue Oct 17 10:22:53 1989
Received: from ucbvax.Berkeley.EDU by megaron (5.59-1.7/15) via SMTP
id AA23606; Tue, 17 Oct 89 10:22:53 MST
Received: from awesome.Berkeley.EDU by ucbvax.Berkeley.EDU (5.61/1.38)
id AA07466; Tue, 17 Oct 89 10:22:52 -0700
Received: from localhost by awesome.berkeley.edu (4.0/SMI-4.0)
id AA18864; Tue, 17 Oct 89 10:24:23 PDT
Message-Id: <8910171724.AA18864@awesome.berkeley.edu>
To: info-sr@arizona.edu
Subject: compute server
Date: Tue, 17 Oct 89 10:24:21 -0700
From: djones%awesome.Berkeley.EDU@ucbvax.Berkeley.EDU
I have a few questions about SR, all relating to creating a "compute server".
First, here's an overview of what I'd like to set up.
The main machine M starts a compute server resource C and some number of
computing tasks A. (These may actually be on different computers)
Each A has two processes. One which does some computing and the another
which queries C to find another A which is "idle". C keeps a list
of which A's are idle.
Questions:
(1) How can an active resource determine its own capability?
ie, how do I assign the proper value to "me" in the example below
resource X
body X
var me : cap X
end X
(2) What is the easiest way to cope with resources that are interdependent,
ie resources that want to "import" each other.
Is the following the only solution?
resource A_stub
op something()
end A_stub
resource B
import A_stub
body B
end B
resource A
extend A_stub
import B
body A
end A
(3) Is there some SR mechanism for "broadcasting"? An alternative to the
"compute server" would be that each A wanting to locate an idle A could
just broadcast a request, and accept the first reply. If this can
be done, can it be done efficiently? (ie so resources don't have to keep
responding to requests to say it is not idle)
(4) Below is an example (attempted) implementation and its output.
If you have the patience ...
Does anyone have any clues why it fails? Also, any style suggestions would
be appreciated. When I run the resulting program, there are two outcomes.
(source in ab.sr at the end)
awesome% srm
awesome% make
sr -c ab.sr
srl -o a.out compute ab main
awesome% a.out fugitive totally >& TMP
awesome% TMP
main: AB will be on:
fugitive
totally
make: active
awesome : compute server ready
awesome : compute server starts
awesome : compute_idler starts
awesome : compute.number( 0 )
make: compute created, machine ID is 0
make: about to create AB
make: creating AB on fugitive
fugitive : ab initial
make: AB 1 has machine id 1
fugitive : ap_spawner, waiting for my cap
fugitive : ab_server
fugitive : ab.number( 1 )
[vm 2] RTS abort: attempting to invoke operation that no longer exists
awesome% a.out fugitive totally
main: AB will be on:
fugitive
totally
make: active
awesome : compute server ready
awesome : compute server starts
awesome : compute_idler starts
awesome : compute.number( 0 )
make: compute created, machine ID is 0
make: about to create AB
make: creating AB on fugitive
fugitive : ab initial
fugitive : ap_spawner, waiting for my cap
fugitive : ab_server
make: AB 1 has machine id 1
fugitive : ab.number( 1 )
srx: can't connect to vm 32 -- not yet initialized
---------------------------- ab.sr ----------------------------
/* AB */
resource ab_basics
op ab_reply(m:cap ab_basics)
op ab_yourcap(m:cap ab_basics)
op ab_work(h:string(100); m:cap ab_basics)
op ab_work_done()
op number() returns n : int
external gethostname(res name:string(*); namelen:int)
end ab_basics
resource compute
import ab_basics
op compute_request(m:cap ab_basics)
op compute_done(m:cap ab_basics)
op compute_unlock()
op compute_lock()
op compute_machines(m[1:*]:cap ab_basics)
op number() returns n:int
external gethostname(res name:string(*); namelen:int)
body compute(n:int)
var h :string(100)
var machine[1:n] :cap ab_basics
var idle[1:n] :int
var n_idle :int
var index :int
initial
call gethostname(h,maxlength(h))
fa i:=1 to n ->
idle[i]:=1
af
index:=1
n_idle:=n
write(h,": compute server ready") flush(stdout)
end
proc number() returns n
n:=mymachine()
write(h,": compute.number(",n,")") flush(stdout)
flush(stdout)
end number
process compute_lock_server
do (true) ->
send compute_unlock()
receive compute_lock()
od
end compute_lock_server
process compute_server
var r :cap ab_basics
write(h,": compute server starts") flush(stdout)
receive compute_machines(machine)
write(h,": compute server knows machines") flush(stdout)
do (true) ->
do (n_idle < 1) ->
write(h,": computer server sleeping") flush(stdout)
nap(5000)
od
receive compute_request(r)
receive compute_unlock()
fa i:=1 to n ->
if (idle[index] > 0) ->
send r.ab_reply(machine[i])
idle[i]:=0
fi
index++
if (index > n) ->
index:=1
fi
af
send compute_lock()
od
end compute_server
process compute_idler
var m :cap ab_basics
write(h,": compute_idler starts") flush(stdout)
do (true) ->
receive compute_done(m)
receive compute_unlock()
fa i:=1 to n ->
if (m = machine[i]) ->
write(h,": compute idler, ",i," becomes idle\n") flush(stdout)
idle[i]:=1
exit
fi
af
send compute_lock()
od
end compute_idler
end compute
resource ab
extend ab_basics
import compute
body ab(c:cap compute)
var h :string(100)
var mycap :cap ab
initial
gethostname(h,maxlength(h))
write(h,": ab initial") flush(stdout)
flush(stdout)
end
proc number() returns n
n:=mymachine()
write(h,": ab.number(",n,")") flush(stdout)
flush(stdout)
end number
process ab_spawner
var m :cap ab
write(h,": ap_spawner, waiting for my cap") flush(stdout)
receive ab_yourcap(mycap)
write(h,": ab_spawner, sleeping") flush(stdout)
nap(4000)
send c.compute_request(mycap)
receive ab_reply(m)
send m.ab_work(h,mycap)
receive ab_work_done()
send c.compute_done(m)
end ab_spawner
process ab_server
var host :string(100)
var m :cap ab
write(h,": ab_server") flush(stdout)
do (true) ->
receive ab_work(host,m)
write(h,": ab_server gets work from ",host," - sleeping") flush(stdout)
nap(10000)
send m.ab_work_done()
write(h,": ab_server done") flush(stdout)
od
end ab_server
final
write(h,": ab final") flush(stdout)
end
end ab
resource main
import compute
import ab
body main()
var n :int
var ab_cap[1:n] :cap ab
initial
var s :string(100)
n:=numargs()
write("main: AB will be on: ")
fa i:=1 to n ->
getarg(i,s)
write(s)
af
flush(stdout)
end
process make
var s :string(100)
var remote :cap vm
var c :cap compute
write("make: active") flush(stdout)
c:=create compute(n) on myvm()
if (c = null) ->
write("make: failed to create a compute") flush(stdout)
stop
fi
write("make: compute created, machine ID is ",c.number()) flush(stdout)
write("make: about to create AB") flush(stdout)
fa i := 1 to n ->
getarg(i,s)
locate(i,s)
remote:=create vm() on i
if (remote = null) ->
write(stderr,"make_ab: can't create vm on",s) flush(stderr)
[] else ->
write("make: creating AB on ",s) flush(stdout)
ab_cap[i]:=create ab(c) on remote
if (ab_cap[i] = null) ->
write("make: create AB on host ",s,", machine ",i," failed.")
flush(stdout)
[] else ->
write("make: AB ",i," has machine id ",ab_cap[i].number())
flush(stdout)
send ab_cap[i].ab_yourcap(ab_cap[i])
write("make: AB notified of its cap")
fi
fi
af
write("make: all AB created, sleeping") flush(stdout)
nap(10000)
write("make: telling server which machines") flush(stdout)
send c.compute_machines(ab_cap)
end make
final
write("main: cleanup") flush(stdout)
end
end main
From olsson@ivy.ucdavis.edu Wed Oct 18 12:02:27 1989
Received: from clover.ucdavis.edu by megaron (5.59-1.7/15) via SMTP
id AA13484; Wed, 18 Oct 89 12:02:27 MST
Received: from ivy.ucdavis.edu by clover.ucdavis.edu (5.59/UCD.EECS.1.11)
id AA22058; Tue, 17 Oct 89 21:03:21 PDT
Received: by ivy.ucdavis.edu (3.2/3.14)
id AA27368; Tue, 17 Oct 89 20:59:31 PDT
Date: Tue, 17 Oct 89 20:59:31 PDT
From: olsson@ivy.ucdavis.edu (Ron Olsson)
Message-Id: <8910180359.AA27368@ivy.ucdavis.edu>
To: djones%awesome.Berkeley.EDU@ucbvax.Berkeley.EDU
Cc: info-sr@arizona.edu
In-Reply-To: djones%awesome.Berkeley.EDU@ucbvax.Berkeley.EDU's message of Tue, 17 Oct 89 10:24:21 -0700 <8910171724.AA18864@awesome.berkeley.edu>
Subject: compute server
Date: Tue, 17 Oct 89 10:24:21 -0700
From: djones%awesome.Berkeley.EDU@ucbvax.Berkeley.EDU
...
Questions:
(1) How can an active resource determine its own capability?
ie, how do I assign the proper value to "me" in the example below
resource X
body X
var me : cap X
end X
me := myresource() (See section 7.5 in the report.)
(2) What is the easiest way to cope with resources that are interdependent,
ie resources that want to "import" each other.
Is the following the only solution?
Maybe not the only one, but a reasonable one. There was a discussion
on info-sr about 2 months ago on this topic; I'll send it to you.
That is a lacking in SR -- something we are remedying in version 2.
(3) Is there some SR mechanism for "broadcasting"? An alternative to the
"compute server" would be that each A wanting to locate an idle A could
just broadcast a request, and accept the first reply. If this can
be done, can it be done efficiently? (ie so resources don't have to keep
responding to requests to say it is not idle)
I didn't take time to look at your application in detail. However,
you might use a co statement, e.g.,
co (i := 1 to N) Acap[i].try -> got := i; exit oc
That will broadcast a request to all in Acap, and continue when one of
them replies, recording that index in got. (You might then use
Acap[got].otherop(...) to invoke otherop in Acap[got].)
(4) Below is an example (attempted) implementation and its output.
If you have the patience ...
Does anyone have any clues why it fails?
I see one big problem, but I haven't tried running a corrected version.
resource main
import compute
import ab
body main()
var n :int
var ab_cap[1:n] :cap ab
ab_cap is allocated with the current value of n, which at this point
is garbage. (It isn't initialized until below in initial.)
initial
var s :string(100)
n:=numargs()
write("main: AB will be on: ")
fa i:=1 to n ->
getarg(i,s)
write(s)
af
flush(stdout)
end
Two possible fixes:
(1) change declaration of n to (and delete assignment to n in initial)
var n :int := numargs()
(2) move declaration of ab_cap to process make (i.e., after initial
has executed and set n).
I didn't try running your program with these fixes, so it might have
other problems too.
From djones%awesome.Berkeley.EDU@ucbvax.Berkeley.EDU Thu Oct 19 10:11:57 1989
Received: from ucbvax.Berkeley.EDU by megaron (5.59-1.7/15) via SMTP
id AA19777; Thu, 19 Oct 89 10:11:57 MST
Received: from awesome.Berkeley.EDU by ucbvax.Berkeley.EDU (5.61/1.38)
id AA07152; Thu, 19 Oct 89 10:11:34 -0700
Received: from localhost by awesome.berkeley.edu (4.0/SMI-4.0)
id AA21372; Wed, 18 Oct 89 15:18:22 PDT
Message-Id: <8910182218.AA21372@awesome.berkeley.edu>
To: info-sr@arizona.edu
Subject: trouble passing "capabilities"
Date: Wed, 18 Oct 89 15:18:21 -0700
From: djones%awesome.Berkeley.EDU@ucbvax.Berkeley.EDU
I am having trouble passing "capabilities" around between processes
in different resources. The following example is a stripped version
of a larger one in which several active resources query a "compute server"
and are returned the "capability" of an idle resource (machine), to which
some work can be sent.
----- synopsis of what is in "simple.sr" at end of this message -----
MAIN creates B
MAIN creates A (telling it who B is)
MAIN informs B who A is
B pings A to check it is there
A asks B for some "other" A which it can ping
B replies to A
A tries to ping and fails.
The value returned to A seems invalid, despite the fact that B just used it
in the same way A is trying to.
----- output -----
% a.out awesome totally
make: b created
make: a created
a_caller: waiting for a reply to request
make: informing b
a: I got pinged
b_server: received request
a_caller: about to ping machine returned by b
b_server: replied
[vm 3] RTS abort: attempting to invoke null operation
(does "vm 3" give a clue? As far as I can tell, 0, 1, 2 are active, not 3.)
%
----- simple.sr -----
resource a_stub
op a_reply(a_stub_cap:cap a_stub)
op a_ping()
end a_stub
resource b
import a_stub
op b_request(a_stub_cap:cap a_stub)
op b_inform(a_stub_cap:cap a_stub)
body b()
process b_server
var a_stub_cap :cap a_stub
var remote :cap a_stub
receive b_inform(a_stub_cap)
call a_stub_cap.a_ping()
receive b_request(remote)
write("b_server: received request") flush(stdout) nap(1000)
send remote.a_reply(a_stub_cap)
write("b_server: replied") flush(stdout) nap(1000)
end b_server
end b
resource a
extend a_stub
import b
body a(b_cap:cap b)
proc a_ping()
write("a: I got pinged") flush(stdout) nap(1000)
end a_ping
process a_caller
var other :cap a
send b_cap.b_request(myresource())
write("a_caller: waiting for a reply to request") flush(stdout) nap(1000)
receive a_reply(other)
write("a_caller: about to ping machine returned by b") flush(stdout) nap(1000)
call other.a_ping()
write("a_caller: other A appears to be alive") flush(stdout)
end a_caller
end a
resource main
import a
import b
body main()
initial
if (numargs() != 2) ->
stop
fi
end
process make
var hostname :string(100)
var a_cap :cap a
var b_cap :cap b
var remote :cap vm
getarg(1,hostname)
locate(1,hostname)
remote:=create vm() on 1
if (remote = null) ->
write("make: can't create vm on ",hostname) flush(stdout)
stop
fi
b_cap:=create b() on remote
if (b_cap = null) ->
write("make: can't create B on ",hostname) flush(stdout)
stop
fi
write("make: b created") flush(stdout) nap(1000)
getarg(2,hostname)
locate(2,hostname)
remote:=create vm() on 2
if (remote = null) ->
write("make: can't create vm on ",hostname) flush(stdout)
stop
fi
a_cap:=create a(b_cap) on remote
if (a_cap = null) ->
write("make: can't create A on ",hostname) flush(stdout)
stop
fi
write("make: a created") flush(stdout) nap(1000)
write("make: informing b") flush(stdout) nap(1000)
send b_cap.b_inform(a_cap)
end make
end main
From olsson@ivy.ucdavis.edu Fri Oct 20 11:27:55 1989
Received: from clover.ucdavis.edu by megaron (5.59-1.7/15) via SMTP
id AA10089; Fri, 20 Oct 89 11:27:55 MST
Received: from ivy.ucdavis.edu by clover.ucdavis.edu (5.59/UCD.EECS.1.11)
id AA11898; Fri, 20 Oct 89 11:30:26 PDT
Received: by ivy.ucdavis.edu (3.2/3.14)
id AA05185; Fri, 20 Oct 89 11:26:20 PDT
Date: Fri, 20 Oct 89 11:26:20 PDT
From: olsson@ivy.ucdavis.edu (Ron Olsson)
Message-Id: <8910201826.AA05185@ivy.ucdavis.edu>
To: djones%awesome.Berkeley.EDU@ucbvax.Berkeley.EDU
Cc: info-sr@arizona.edu
In-Reply-To: djones%awesome.Berkeley.EDU@ucbvax.Berkeley.EDU's message of Wed, 18 Oct 89 15:18:21 -0700 <8910182218.AA21372@awesome.berkeley.edu>
Subject: trouble passing "capabilities"
Date: Wed, 18 Oct 89 15:18:21 -0700
From: djones%awesome.Berkeley.EDU@ucbvax.Berkeley.EDU
I am having trouble passing "capabilities" around between processes
...
You've discovered a new bug, sorry to say. It seems to be caused by
extending a resource that contains a capability for itself. In your
program that happens
resource a_stub
op a_reply(a_stub_cap:cap a_stub)
op a_ping()
end a_stub
...
resource a
extend a_stub
import b
body a(b_cap:cap b)
process a_caller
var other :cap a
send b_cap.b_request(myresource())
write("a_caller: waiting for a reply to request") ...
receive a_reply(other)
write("a_caller: about to ping machine returned by b") ...
call other.a_ping()
write("a_caller: other A appears to be alive") flush(stdout)
end a_caller
end a
The exact problem is that we generate bad code for `receive
a_reply(other)'; it doesn't set other's value correctly. In
particular, we don't copy into other, so by chance other's value is
null and the program dies on the call.
The workaround is to not use the extend. Replace extend with the
equivalent definitions (and change caps for the extended resource to
caps for the current one). E.g., change your program to the following.
resource a_stub
op a_reply(a_stub_cap:cap a_stub)
op a_ping()
end a_stub
resource b
import a_stub
op b_request(a_stub_cap:cap a_stub)
op b_inform(a_stub_cap:cap a_stub)
body b()
process b_server
var a_stub_cap :cap a_stub
var remote :cap a_stub
receive b_inform(a_stub_cap)
call a_stub_cap.a_ping()
receive b_request(remote)
write("b_server: received request") flush(stdout) nap(1000)
send remote.a_reply(a_stub_cap)
write("b_server: replied") flush(stdout) nap(1000)
end b_server
end b
resource a
# extend a_stub
op a_reply(a_stub_cap:cap a)
op a_ping()
import b
body a(b_cap:cap b)
proc a_ping()
write("a: I got pinged") flush(stdout) nap(1000)
end a_ping
process a_caller
var other :cap a
send b_cap.b_request(myresource())
write("a_caller: waiting for a reply to request") flush(stdout) nap(1000)
receive a_reply(other)
#
# bogus generated code uses memcpy(_,_,0) to copy into other for receive.
#
write("a_caller: about to ping machine returned by b") flush(stdout) nap(1000)
if other = noop -> write("other is noop")
[] other = null -> write("other is null")
[] else -> write("other is ok")
fi
call other.a_ping()
write("a_caller: other A appears to be alive") flush(stdout)
end a_caller
end a
resource main
import a
import b
body main()
process make
var a_cap :cap a
var b_cap :cap b
b_cap:=create b()
write("make: b created") flush(stdout) nap(1000)
a_cap:=create a(b_cap)
write("make: a created") flush(stdout) nap(1000)
send b_cap.b_inform(a_cap)
write("make: b informed") flush(stdout) nap(1000)
end make
end main
From gmt Thu Oct 26 17:43:29 1989
Date: Thu, 26 Oct 89 17:43:29 MST
From: "Gregg Townsend" <gmt>
Message-Id: <8910270043.AA13081@megaron.arizona.edu>
Received: by megaron.arizona.edu (5.59-1.7/15)
id AA13081; Thu, 26 Oct 89 17:43:29 MST
To: info-sr
Subject: New Context Switch Code for Sun-4 Systems
Several ill-defined runtime problems have been reported when running SR
on the SPARC (Sun4) architecture. The context switching code (rts/sparc.s)
is believed to be responsible.
Below is an alternate implementation of context switching for Sun4 systems.
This code uses the Sun lightweight process library and should be used in
place of the current assembly language code.
Use of this code requires three minor changes in the SR source file hierarchy:
1. Install the code below in a new file "rts/sunlwp.c".
2. Edit "rts/Makefile" and change the first mention of "machine.o"
(in the definition of OBJ) to "sunlwp.o".
3. Edit "srl/gen.c" and insert a line
*argp++ = "-llwp";
five lines before the end of file, immediately before the line
*argp++ = 0;
After making those changes, just build or rebuild SR in the usual manner
as described in the installation documentation.
This code will also run on Sun3 systems, but we do not recommend installing
it there because it is slower than the existing code.
Gregg Townsend / Computer Science Dept / Univ of Arizona / Tucson, AZ 85721
+1 602 621 4325 gmt@cs.arizona.edu 110 57 16 W / 32 13 45 N / +761m
---------------------- cut here, save as rts/sunlwp.c ----------------------
/* sunlwp.c - SR context switching routines using Sun lightweight processes */
#include <stdio.h>
#include <lwp/lwp.h>
#include <lwp/stackdep.h>
#define CON_MAGIC 2079447381 /* an arbitrary (and unlikely) magic number */
#define GOOD_PRI 2 /* priority for real threads */
#define KILL_PRI 1 /* priority for the killer thread */
#define KILL_STK 512 /* stack size for killer thread */
#define lwcall(text,retval) if ((retval) != 0) lwerror (text);
typedef struct { /* context header: */
thread_t tid; /* thread id for lwp library */
int magic; /* magic number for integrity checking */
} con_hdr, *con_ptr;
static con_ptr curr; /* current context pointer */
static void startup(), initkiller(), killer(), lwerror();
/************************* EXTERNAL ROUTINES *************************/
/* sr_build_context - create a new SR process context.
*
* We put a context header (see above) at the beginning of the space
* and use the rest for the lwp stack.
*/
void
sr_build_context (entry, context, size, arg1, arg2, arg3, arg4)
void (*entry)();
char *context;
int size;
int arg1, arg2, arg3, arg4;
{
static int first = 1; /* first-call flag */
con_ptr cp = (con_ptr) context; /* context pointer */
/* initialize a few things the first time we're called */
if (first) {
lwcall("set maxpri", pod_setmaxpri (GOOD_PRI)); /* set priority range */
initkiller (); /* init killer thread */
first = 0; /* note init done */
}
cp = (con_ptr) context; /* get context block pointer */
if (cp->magic == CON_MAGIC) /* if reusing stack, kill previous */
lwcall("destroy lwp", lwp_destroy (cp->tid));
lwcall("create lwp", /* create new thread */
lwp_create (&cp->tid, startup, GOOD_PRI, LWPSUSPEND + LWPNOLASTRITES,
context + size, 5, entry, arg1, arg2, arg3, arg4));
cp->magic = CON_MAGIC; /* set magic word for stack checking */
}
/* sr_chg_context() - switch to a different SR process */
void
sr_chg_context (context)
char *context;
{
con_ptr cp = (con_ptr) context;
if (curr != 0 && curr->magic != CON_MAGIC) /* check curr stk looks good */
sr_stk_overflow ();
if (cp == curr) /* nothing to do on change to self */
return;
if (cp->magic != CON_MAGIC) /* check that new stack looks good */
sr_stk_corrupted ();
lwcall("resume", lwp_resume (cp->tid)); /* unsuspend new process */
curr = cp; /* remember current pointer */
lwcall("suspend", lwp_suspend (SELF)); /* suspend self, yield to new */
}
/* sr_check_stk() - check for stack overflow.
*
* We check to see if the magic word has been overwritten.
* This isn't foolproof, but it will catch some errors.
*/
void
sr_check_stk ()
{
if (curr->magic != CON_MAGIC)
sr_stk_overflow ();
}
/************************* INTERNAL ROUTINES *************************/
/* startup() - call the entry point of a newly created SR process.
*
* If it ever returns, signal stack underflow.
*/
static void
startup (entry, arg1, arg2, arg3, arg4)
void (*entry)();
int arg1, arg2, arg3, arg4;
{
(*entry) (arg1, arg2, arg3, arg4);
sr_stk_underflow ();
}
/* initkiller() - set up a thread to catch exit calls.
*
* The problem is that exit() is caught by the lwp library and doesn't
* really exit; so, we create a low-priority killer thread that will do so.
* If the executing SR process exits, the killer thread will get control
* because all other SR processes are still suspended.
*/
static void
initkiller ()
{
thread_t tid;
static char killstk[KILL_STK];
lwcall("create killer",
lwp_create (&tid, killer, KILL_PRI, LWPNOLASTRITES,
killstk + KILL_STK, 0));
}
/* killer() - the actual code executed by the killer thread. */
static void
killer ()
{
pod_exit (pod_getexit ());
}
/* lwerror(text) - abort with message from lightweight process error */
static void
lwerror (text)
char *text;
{
fprintf (stderr, "lwp error: ");
lwp_perror (text);
pod_exit (1);
}
From bina@acsu.buffalo.edu Sun Nov 5 13:07:08 1989
Received: from autarch.acsu.buffalo.edu by megaron.arizona.edu (5.59-1.7/15) via SMTP
id AA01515; Sun, 5 Nov 89 13:07:08 MST
Received: by autarch.acsu.buffalo.edu (4.0/1.35)
id AA12226; Sun, 5 Nov 89 15:07:06 EST
Date: Sun, 5 Nov 89 15:07:06 EST
From: bina@acsu.buffalo.edu (Bina Ramamurthy)
Message-Id: <8911052007.AA12226@autarch.acsu.buffalo.edu>
To: info-sr@cs.arizona.edu
Subject: want info
I am an instructor at SUNY Buffalo. I am interested in knowing
whether you are using SR in any of your regular undergraduate
courses like operating systems, computer architecture.
Could you also give me list of all the courses using SR and
the hardware set up (what king machines etc.) you are using
it on?
bina
bina@gort.cc.buffalo.edu
From greg Sun Nov 5 19:11:10 1989
Received: from paloverde.cs.arizona.edu by megaron.arizona.edu (5.59-1.7/15) via SMTP
id AA13131; Sun, 5 Nov 89 19:11:10 MST
Date: Sun, 5 Nov 89 19:10:59 MST
From: "Greg Andrews" <greg>
Message-Id: <8911060210.AA08615@paloverde>
Received: by paloverde; Sun, 5 Nov 89 19:10:59 MST
In-Reply-To: <8911052007.AA12226@autarch.acsu.buffalo.edu>
To: bina@acsu.buffalo.edu
Subject: Re: want info
Cc: info-sr
We are not yet using SR in any undergraduate courses.
(We just began an undergraduate major this year so do
not have as many undergraduate courses as we eventually
will.)
SR is used for all programming projects in our
course on concurrent programming. It is also used -- typically
at student discretion -- in graduate courses on operating
systems, networks, and parallel algorithms. It has also been
used in a course on logic programming (two students used SR
to implement an interpreter for a variant of concurrent Prolog).
By student discretion I mean that use of SR is not required;
instead some students who already know it choose to do their
course projects in SR.
For your information, Ron Olsson and I are writing a book
"Concurrent Programming in SR" to be published in 1991 by
Benjamin/Cummings. If you are interested in using SR for
classroom projects, this should make it a *lot* easier on
you and your students. Also, we will have a second (much
improved naturally) version of SR out in a year -- and the
book will describe that version.
-- Greg Andrews
From bina@cs.Buffalo.EDU Mon Nov 6 08:02:16 1989
Received: from gort.cs.Buffalo.EDU by megaron.arizona.edu (5.59-1.7/15) via SMTP
id AA08071; Mon, 6 Nov 89 08:02:16 MST
Received: by gort.cs.Buffalo.EDU (5.61/1.01)
id AA19585; Mon, 6 Nov 89 10:02:17 -0500
Date: Mon, 6 Nov 89 10:02:17 -0500
From: bina@cs.Buffalo.EDU (Bina Ramamurthy)
Message-Id: <8911061502.AA19585@gort.cs.Buffalo.EDU>
To: bina@acsu.buffalo.edu, greg@cs.arizona.edu
Subject: Re: want info
Cc: info-sr@cs.arizona.edu
Thanks. Let me try the version of SR we have and then
write to you if I have any questions.
bina
From djones%awesome.Berkeley.EDU@ucbvax.Berkeley.EDU Sat Nov 18 01:04:00 1989
Received: from ucbvax.Berkeley.EDU by megaron.arizona.edu (5.59-1.7/15) via SMTP
id AA12117; Sat, 18 Nov 89 01:04:00 MST
Received: from awesome.Berkeley.EDU by ucbvax.Berkeley.EDU (5.61/1.39)
id AA17598; Sat, 18 Nov 89 00:03:19 -0800
Received: from localhost by awesome.berkeley.edu (4.0/SMI-4.0)
id AA09410; Sat, 18 Nov 89 00:05:23 PST
Message-Id: <8911180805.AA09410@awesome.berkeley.edu>
To: info-sr@arizona.edu
Subject: string(*) vs string(100)
Date: Sat, 18 Nov 89 00:05:22 -0800
From: djones%awesome.Berkeley.EDU@ucbvax.Berkeley.EDU
What is the difference between :
op ping(from:string(*); to:string(*))
and
op ping(from:string(100); res to:string(100))
when they will be implemented as
var myhost:string(100)
initial
gethostname(myhost,maxlength(myhost))
end initial
proc ping(from,to)
write("pinged by",from)
to:=myhost
end ping
...
var other_host:string(100)
call other_machine.ping(myhost,other_host)
write(other_host,"is alive")
David Jones
djones@awesome.berkeley.edu
From olsson@ivy.ucdavis.edu Sat Nov 18 02:17:02 1989
Received: from clover.ucdavis.edu by megaron.arizona.edu (5.59-1.7/15) via SMTP
id AA16340; Sat, 18 Nov 89 02:17:02 MST
Received: from ivy.ucdavis.edu by clover.ucdavis.edu (5.59/UCD.EECS.1.11)
id AA03245; Sat, 18 Nov 89 01:18:32 PST
Received: by ivy.ucdavis.edu (3.2/3.14)
id AA27610; Sat, 18 Nov 89 01:16:47 PST
Date: Sat, 18 Nov 89 01:16:47 PST
From: olsson@ivy.ucdavis.edu (Ron Olsson)
Message-Id: <8911180916.AA27610@ivy.ucdavis.edu>
To: djones%awesome.Berkeley.EDU@ucbvax.Berkeley.EDU
Cc: info-sr@cs.arizona.edu
In-Reply-To: djones%awesome.Berkeley.EDU@ucbvax.Berkeley.EDU's message of Sat, 18 Nov 89 00:05:22 -0800 <8911180805.AA09410@awesome.berkeley.edu>
Subject: string(*) vs string(100)
Date: Sat, 18 Nov 89 00:05:22 -0800
From: djones%awesome.Berkeley.EDU@ucbvax.Berkeley.EDU
What is the difference between :
op ping(from:string(*); to:string(*))
and
op ping(from:string(100); res to:string(100))
...
The effect should be the same in your example ... provided that
ping's 2nd parameter in the first declaration is made a res parameter
too; otherwise, it won't get copied back. (And the name of ping's 2nd
parameter is changed so it isn't a reserved word.)
(I'm not sure I completely understood your question. If not, let me know.)
From djones%awesome.Berkeley.EDU@ucbvax.Berkeley.EDU Sat Nov 18 03:10:42 1989
Received: from ucbvax.Berkeley.EDU by megaron.arizona.edu (5.59-1.7/15) via SMTP
id AA20136; Sat, 18 Nov 89 03:10:42 MST
Received: from awesome.Berkeley.EDU by ucbvax.Berkeley.EDU (5.61/1.39)
id AA22727; Sat, 18 Nov 89 02:10:00 -0800
Received: from localhost by awesome.berkeley.edu (4.0/SMI-4.0)
id AA10157; Sat, 18 Nov 89 02:12:03 PST
Message-Id: <8911181012.AA10157@awesome.berkeley.edu>
To: info-sr@arizona.edu
Subject: possible bug in SR compiler involving ENUM
Date: Sat, 18 Nov 89 02:12:01 -0800
From: djones%awesome.Berkeley.EDU@ucbvax.Berkeley.EDU
Included below is "bug.sr". It is trimmed down from a much larger
application I was working on, and so makes little sense on its own.
On our setup, this causes a segmentation fault when you try:
% sr -c bug.sr
A little poking in the compiler seems to suggest that it is
processing the line:
send o_cap.hello(mycap,x)
At this point, is checking (I think) that "mycap" which is "cap a" is
compatible with "cap a_stub" by checking their structural equivalence.
It tries to see if the two "e_type"s of "a" and "a_stub" are the same
and ends up charging off the list, since it expects it to be NULL terminated,
but it is not. It does not check the "s_size", which seems to record
the number of enumeration literals in the type. The s_size *does* seem
to be consulted in decl.c.
The relevant code is in sr/sr/sigcmp.c, around lines 70-80
----------------- bug.sr ----------------
resource a_stub
type e_type = enum (alpha, beta, gamma)
op function()
end a_stub
resource other
import a_stub
op hello(a_cap:cap a_stub; x:e_type)
body other()
process listener
var a_cap :cap a_stub
var y:e_type
receive hello(a_cap,y)
end listener
end other
resource a
type e_type = enum (alpha, beta, gamma)
op function()
import other
body a(o_cap:cap other)
var mycap :cap a
initial
mycap:=myresource()
end initial
proc function()
end function
process server
var x:e_type
x:=beta
send o_cap.hello(mycap,x)
end server
end a
resource main
body main()
end main
From djones%awesome.Berkeley.EDU@ucbvax.Berkeley.EDU Sat Nov 18 05:03:05 1989
Received: from ucbvax.Berkeley.EDU by megaron.arizona.edu (5.59-1.7/15) via SMTP
id AA25581; Sat, 18 Nov 89 05:03:05 MST
Received: from awesome.Berkeley.EDU by ucbvax.Berkeley.EDU (5.61/1.39)
id AA28473; Sat, 18 Nov 89 04:02:24 -0800
Received: from localhost by awesome.berkeley.edu (4.0/SMI-4.0)
id AA11281; Sat, 18 Nov 89 04:04:28 PST
Message-Id: <8911181204.AA11281@awesome.berkeley.edu>
To: info-sr@arizona.edu
Subject: probable SR runtime bug, memory not freed
Date: Sat, 18 Nov 89 04:04:22 -0800
From: djones%awesome.Berkeley.EDU@ucbvax.Berkeley.EDU
For certain SR programs, I have noticed their SIZE continually increases
during runtime and if left long enough, there is a "[vm N] out of memory" error.
Perhaps buffers (for send/receive to remote machines?) are being
allocated, but never freed.
Has anyone else noticed this?
Dave
djones@awesome.berkeley.edu
From djones%awesome.Berkeley.EDU@ucbvax.Berkeley.EDU Mon Nov 20 02:25:42 1989
Received: from ucbvax.Berkeley.EDU by megaron.arizona.edu (5.59-1.7/15) via SMTP
id AA07942; Mon, 20 Nov 89 02:25:42 MST
Received: from awesome.Berkeley.EDU by ucbvax.Berkeley.EDU (5.61/1.39)
id AA15573; Mon, 20 Nov 89 01:24:57 -0800
Received: from localhost by awesome.berkeley.edu (4.0/SMI-4.0)
id AA16511; Mon, 20 Nov 89 01:27:05 PST
Message-Id: <8911200927.AA16511@awesome.berkeley.edu>
To: info-sr@arizona.edu
Subject: re: memory allocation bug at run time?
Date: Mon, 20 Nov 89 01:27:02 -0800
From: djones%awesome.Berkeley.EDU@ucbvax.Berkeley.EDU
The following example is a simple case of two processes (on different machines)
sending messages to each other. Using "ps", or "top", one can watch the
process size slowly, but continuously, rising ... until we get an
"out of memeory" error.
I tried to check alloc's and free's (with setenv SRXDEBUG FFFFF), but
I didn't learn anything.
awesome% srm
awesome% make
awesome% a.out totally
----------------- membug.sr ------------------------
/* Memory allocation bug exerciser */
resource main_stub
op done()
end main_stub
resource ab
op ab_work()
import main_stub
body ab(m:cap main_stub)
process ab_server
do (true) ->
receive ab_work()
send m.done()
od
end ab_server
end ab
resource main
op done()
import ab
body main()
var n :int
initial
n:=numargs()
if (n != 1) ->
write("give exatcly one host name")
flush(stdout)
stop
fi
end
process make
var s :string(100)
var ab_cap :cap ab
var remote :cap vm
getarg(1,s)
locate(1,s)
remote:=create vm() on 1
ab_cap:=create ab(myresource()) on remote
do (true) ->
send ab_cap.ab_work()
receive done()
od
end make
end main
From gmt Mon Nov 20 11:02:36 1989
Date: Mon, 20 Nov 89 11:02:36 MST
From: "Gregg Townsend" <gmt>
Message-Id: <8911201802.AA08638@megaron.arizona.edu>
Received: by megaron.arizona.edu (5.59-1.7/15)
id AA08638; Mon, 20 Nov 89 11:02:36 MST
To: djones@awesome.berkeley.edu
Subject: bug reports
Cc: info-sr
Thank you for the bug reports.
We're aware of several problems in both of those areas: signature checking
in the compiler and memory allocation at runtime. We hope to fix those
in the next version of the SR system, and will retain your test programs
to help verify this.
In general, bug reports should be addressed to sr-project@cs.arizona.edu,
unless there's a reason for the whole info-sr list to see them.
Gregg Townsend / Computer Science Dept / Univ of Arizona / Tucson, AZ 85721
+1 602 621 4325 gmt@cs.arizona.edu 110 57 16 W / 32 13 45 N / +758m